package service

import (
	"bytes"
	"fmt"
	"regexp"
	"strings"
	"crypto/md5"
	"encoding/hex"

	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/extension"
	"github.com/yuin/goldmark/parser"
	"github.com/yuin/goldmark/renderer/html"
	"github.com/sirupsen/logrus"
)

// MarkdownService 处理Markdown相关的业务逻辑
type MarkdownService struct {
	md            goldmark.Markdown
	logger        *logrus.Logger
	renderService *RenderService
}

// NewMarkdownService 创建新的Markdown服务实例
func NewMarkdownService(logger *logrus.Logger, renderService *RenderService) *MarkdownService {
	md := goldmark.New(
		goldmark.WithExtensions(
			extension.GFM,        // GitHub Flavored Markdown
			extension.Table,      // 表格支持
			extension.Strikethrough, // 删除线
			extension.TaskList,   // 任务列表
			extension.Linkify,    // 自动链接
		),
		goldmark.WithParserOptions(
			parser.WithAutoHeadingID(), // 自动生成标题ID
		),
		goldmark.WithRendererOptions(
			html.WithHardWraps(),   // 硬换行
			html.WithXHTML(),       // XHTML兼容
			html.WithUnsafe(),      // 允许原始HTML（根据配置）
		),
	)

	return &MarkdownService{
		md:            md,
		logger:        logger,
		renderService: renderService,
	}
}

// RenderToHTML 将Markdown内容渲染为HTML
func (s *MarkdownService) RenderToHTML(content string) (string, error) {
	return s.ParseMarkdown(content)
}

// ParseMarkdown 解析Markdown内容为HTML
func (s *MarkdownService) ParseMarkdown(content string) (string, error) {
	var buf bytes.Buffer
	
	// 预处理内容
	content = s.preprocessContent(content)
	
	// 转换Markdown为HTML
	if err := s.md.Convert([]byte(content), &buf); err != nil {
		return "", fmt.Errorf("failed to convert markdown: %w", err)
	}
	
	html := buf.String()
	
	// 后处理HTML
	html = s.postprocessHTML(html)
	
	return html, nil
}

// preprocessContent 预处理Markdown内容
func (s *MarkdownService) preprocessContent(content string) string {
	// 处理数学公式
	content = s.processMathFormulas(content)
	
	// 处理图表
	content = s.processCharts(content)
	
	return content
}

// processMathFormulas 处理LaTeX数学公式，支持KaTeX
func (s *MarkdownService) processMathFormulas(content string) string {
	// 处理块级公式 $$...$$（必须先处理，避免与行内公式冲突）
	blockPattern := regexp.MustCompile(`(?s)\$\$\s*\n?(.*?)\n?\s*\$\$`)
	content = blockPattern.ReplaceAllStringFunc(content, func(match string) string {
		formula := blockPattern.FindStringSubmatch(match)[1]
		formula = strings.TrimSpace(formula)
		hash := s.generateHash(formula)
		return fmt.Sprintf(`<div class="katex-block" data-formula="%s" data-hash="%s">%s</div>`, 
			strings.ReplaceAll(formula, `"`, `&quot;`), hash, formula)
	})
	
	// 处理行内公式 $...$
	inlinePattern := regexp.MustCompile(`\$([^$\n]+)\$`)
	content = inlinePattern.ReplaceAllStringFunc(content, func(match string) string {
		formula := inlinePattern.FindStringSubmatch(match)[1]
		formula = strings.TrimSpace(formula)
		hash := s.generateHash(formula)
		return fmt.Sprintf(`<span class="katex-inline" data-formula="%s" data-hash="%s">%s</span>`, 
			strings.ReplaceAll(formula, `"`, `&quot;`), hash, formula)
	})
	
	return content
}

// generateHash 生成内容的MD5哈希值
func (s *MarkdownService) generateHash(content string) string {
	hash := md5.Sum([]byte(content))
	return hex.EncodeToString(hash[:])
}

// processCharts 处理图表代码块
func (s *MarkdownService) processCharts(content string) string {
	// 支持的图表类型
	chartTypes := []string{"mermaid", "plantuml", "flowchart", "sequence", "gantt", "pie", "graph"}
	
	for _, chartType := range chartTypes {
		pattern := regexp.MustCompile(fmt.Sprintf("```%s\\s*\\n([\\s\\S]*?)\\n```", chartType))
		content = pattern.ReplaceAllStringFunc(content, func(match string) string {
			chartCode := pattern.FindStringSubmatch(match)[1]
			chartCode = strings.TrimSpace(chartCode)
			hash := s.generateHash(chartCode)
			
			// 根据图表类型设置不同的CSS类
			cssClass := fmt.Sprintf("%s-chart", chartType)
			if chartType == "sequence" || chartType == "gantt" || chartType == "pie" || chartType == "graph" {
				cssClass = "mermaid-chart" // 这些都是Mermaid的子类型
			}
			
			return fmt.Sprintf(`<div class="%s" data-chart="%s" data-type="%s" data-hash="%s" data-render="pending">
				<div class="chart-loading">正在渲染图表...</div>
				<pre class="chart-source" style="display:none;">%s</pre>
			</div>`, 
				cssClass,
				strings.ReplaceAll(chartCode, `"`, `&quot;`), 
				chartType,
				hash,
				chartCode)
		})
	}
	
	return content
}

// postprocessHTML 后处理HTML内容
func (s *MarkdownService) postprocessHTML(html string) string {
	// 为代码块添加语言类
	codePattern := regexp.MustCompile(`<pre><code class="language-(\w+)">`)
	html = codePattern.ReplaceAllString(html, `<pre><code class="language-$1 hljs">`)
	
	// 为表格添加响应式包装
	tablePattern := regexp.MustCompile(`<table>`)
	html = tablePattern.ReplaceAllString(html, `<div class="table-responsive"><table class="table">`)
	
	tableEndPattern := regexp.MustCompile(`</table>`)
	html = tableEndPattern.ReplaceAllString(html, `</table></div>`)
	
	// 为图片添加响应式类
	imgPattern := regexp.MustCompile(`<img([^>]+)>`)
	html = imgPattern.ReplaceAllString(html, `<img class="img-responsive"$1>`)
	
	return html
}

// GetWordCount 获取文档字数统计
func (s *MarkdownService) GetWordCount(content string) map[string]int {
	// 移除Markdown标记
	text := s.stripMarkdown(content)
	
	// 统计字符数（包括中文）
	chars := len([]rune(text))
	
	// 统计单词数（英文）
	words := len(strings.Fields(text))
	
	// 统计行数
	lines := len(strings.Split(content, "\n"))
	
	// 统计段落数
	paragraphs := len(strings.Split(strings.TrimSpace(content), "\n\n"))
	
	return map[string]int{
		"characters": chars,
		"words":      words,
		"lines":      lines,
		"paragraphs": paragraphs,
	}
}

// stripMarkdown 移除Markdown标记
func (s *MarkdownService) stripMarkdown(content string) string {
	// 移除标题标记
	content = regexp.MustCompile(`^#+\s*`).ReplaceAllString(content, "")
	
	// 移除粗体和斜体
	content = regexp.MustCompile(`\*\*([^*]+)\*\*`).ReplaceAllString(content, "$1")
	content = regexp.MustCompile(`\*([^*]+)\*`).ReplaceAllString(content, "$1")
	
	// 移除链接
	content = regexp.MustCompile(`\[([^\]]+)\]\([^)]+\)`).ReplaceAllString(content, "$1")
	
	// 移除代码标记
	content = regexp.MustCompile("`([^`]+)`").ReplaceAllString(content, "$1")
	
	// 移除引用标记
	content = regexp.MustCompile(`^>\s*`).ReplaceAllString(content, "")
	
	return content
}

// ParseMarkdownWithMetadata 解析Markdown并提取元数据
func (s *MarkdownService) ParseMarkdownWithMetadata(content string) (map[string]interface{}, error) {
	html, err := s.ParseMarkdown(content)
	if err != nil {
		return nil, err
	}
	
	wordCount := s.GetWordCount(content)
	
	// 提取标题
	headings := s.extractHeadings(content)
	
	// 提取图表信息
	charts := s.extractCharts(content)
	
	// 提取数学公式
	formulas := s.extractFormulas(content)
	
	// 提取链接
	links := s.extractLinks(content)
	
	// 提取图片
	images := s.extractImages(content)
	
	return map[string]interface{}{
		"html":       html,
		"word_count": wordCount,
		"headings":   headings,
		"charts":     charts,
		"formulas":   formulas,
		"links":      links,
		"images":     images,
		"toc":        s.generateTOC(headings),
	}, nil
}

// extractHeadings 提取标题
func (s *MarkdownService) extractHeadings(content string) []map[string]interface{} {
	headingPattern := regexp.MustCompile(`^(#{1,6})\s+(.+)$`)
	lines := strings.Split(content, "\n")
	var headings []map[string]interface{}
	
	for i, line := range lines {
		if matches := headingPattern.FindStringSubmatch(line); matches != nil {
			level := len(matches[1])
			title := strings.TrimSpace(matches[2])
			id := strings.ToLower(regexp.MustCompile(`[^a-zA-Z0-9\-_]`).ReplaceAllString(title, "-"))
			
			headings = append(headings, map[string]interface{}{
				"level": level,
				"title": title,
				"id":    id,
				"line":  i + 1,
			})
		}
	}
	
	return headings
}

// extractCharts 提取图表信息
func (s *MarkdownService) extractCharts(content string) []map[string]interface{} {
	var charts []map[string]interface{}
	chartTypes := []string{"mermaid", "plantuml", "flowchart", "sequence", "gantt", "pie", "graph"}
	
	for _, chartType := range chartTypes {
		pattern := regexp.MustCompile(fmt.Sprintf("```%s\\s*\\n([\\s\\S]*?)\\n```", chartType))
		matches := pattern.FindAllStringSubmatch(content, -1)
		
		for _, match := range matches {
			chartCode := strings.TrimSpace(match[1])
			charts = append(charts, map[string]interface{}{
				"type":    chartType,
				"content": chartCode,
				"hash":    s.generateHash(chartCode),
				"lines":   len(strings.Split(chartCode, "\n")),
			})
		}
	}
	
	return charts
}

// extractFormulas 提取数学公式
func (s *MarkdownService) extractFormulas(content string) []map[string]interface{} {
	var formulas []map[string]interface{}
	
	// 块级公式
	blockPattern := regexp.MustCompile(`(?s)\$\$\s*\n?(.*?)\n?\s*\$\$`)
	blockMatches := blockPattern.FindAllStringSubmatch(content, -1)
	for _, match := range blockMatches {
		formula := strings.TrimSpace(match[1])
		formulas = append(formulas, map[string]interface{}{
			"type":    "block",
			"content": formula,
			"hash":    s.generateHash(formula),
		})
	}
	
	// 行内公式
	inlinePattern := regexp.MustCompile(`\$([^$\n]+)\$`)
	inlineMatches := inlinePattern.FindAllStringSubmatch(content, -1)
	for _, match := range inlineMatches {
		formula := strings.TrimSpace(match[1])
		formulas = append(formulas, map[string]interface{}{
			"type":    "inline",
			"content": formula,
			"hash":    s.generateHash(formula),
		})
	}
	
	return formulas
}

// extractLinks 提取链接
func (s *MarkdownService) extractLinks(content string) []map[string]interface{} {
	var links []map[string]interface{}
	
	// Markdown链接格式 [text](url)
	linkPattern := regexp.MustCompile(`\[([^\]]+)\]\(([^)]+)\)`)
	matches := linkPattern.FindAllStringSubmatch(content, -1)
	
	for _, match := range matches {
		links = append(links, map[string]interface{}{
			"text": match[1],
			"url":  match[2],
			"type": "markdown",
		})
	}
	
	// 自动链接
	urlPattern := regexp.MustCompile(`https?://[^\s]+`)
	urlMatches := urlPattern.FindAllString(content, -1)
	
	for _, url := range urlMatches {
		links = append(links, map[string]interface{}{
			"text": url,
			"url":  url,
			"type": "auto",
		})
	}
	
	return links
}

// extractImages 提取图片
func (s *MarkdownService) extractImages(content string) []map[string]interface{} {
	var images []map[string]interface{}
	
	// Markdown图片格式 ![alt](src)
	imagePattern := regexp.MustCompile(`!\[([^\]]*)\]\(([^)]+)\)`)
	matches := imagePattern.FindAllStringSubmatch(content, -1)
	
	for _, match := range matches {
		images = append(images, map[string]interface{}{
			"alt": match[1],
			"src": match[2],
		})
	}
	
	return images
}

// generateTOC 生成目录
func (s *MarkdownService) generateTOC(headings []map[string]interface{}) string {
	if len(headings) == 0 {
		return ""
	}
	
	var toc strings.Builder
	toc.WriteString("<div class=\"toc\">\n")
	toc.WriteString("<h3>目录</h3>\n")
	toc.WriteString("<ul>\n")
	
	for _, heading := range headings {
		level := heading["level"].(int)
		title := heading["title"].(string)
		id := heading["id"].(string)
		
		indent := strings.Repeat("  ", level-1)
		toc.WriteString(fmt.Sprintf("%s<li><a href=\"#%s\">%s</a></li>\n", indent, id, title))
	}
	
	toc.WriteString("</ul>\n")
	toc.WriteString("</div>\n")
	
	return toc.String()
}

// ValidateMarkdown 验证Markdown语法
func (s *MarkdownService) ValidateMarkdown(content string) []map[string]interface{} {
	var issues []map[string]interface{}
	lines := strings.Split(content, "\n")
	
	for i, line := range lines {
		lineNum := i + 1
		
		// 检查未闭合的代码块
		if strings.HasPrefix(line, "```") {
			// 简单检查，实际应该更复杂
			codeBlockCount := strings.Count(content, "```")
			if codeBlockCount%2 != 0 {
				issues = append(issues, map[string]interface{}{
					"type":    "warning",
					"line":    lineNum,
					"message": "可能存在未闭合的代码块",
				})
			}
		}
		
		// 检查链接格式
		if strings.Contains(line, "](") && !regexp.MustCompile(`\[.*\]\(.*\)`).MatchString(line) {
			issues = append(issues, map[string]interface{}{
				"type":    "error",
				"line":    lineNum,
				"message": "链接格式不正确",
			})
		}
		
		// 检查图片格式
		if strings.Contains(line, "![") && !regexp.MustCompile(`!\[.*\]\(.*\)`).MatchString(line) {
			issues = append(issues, map[string]interface{}{
				"type":    "error",
				"line":    lineNum,
				"message": "图片格式不正确",
			})
		}
	}
	
	return issues
}